package com.instwall.rpccallnumclient;

import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.NonNull;

import com.instwall.callnumserver.ICallNumAidlInterface;
import com.instwall.callnumserver.ICallNumListener;

import ashy.earl.common.util.Client;

public class CallNumClient extends Client<ICallNumAidlInterface> {

    private static final String TAG = CallNumClient.class.getName();
    private static final String SERVICE_PKG = "com.instwall.callnum";
    private static final String SERVICE_NAME = "com.instwall.callnumserver.service.CallNumService";
    private static CallNumClient sSelf;
    private final byte[] call_lock = new byte[0];
    private Handler mHandler;
    private ModuleImpl moduleImpl;
    private ICallNumAidlInterface service;


    private static final int CALLNULL_WHAT_01 = 0x101;

    private CallNumClient() {
        super(SERVICE_PKG, SERVICE_NAME, TAG);
    }

    public static CallNumClient get() {
        if (sSelf != null) return sSelf;
        synchronized (CallNumClient.class) {
            if (sSelf == null) sSelf = new CallNumClient();
        }
        return sSelf;
    }

    public void installCallNumClient(Context context) {
        if (isConnectRequested()) return;
        connectService(context);
    }

    private static Handler.Callback mHandlerCallBack = new Handler.Callback() {
        @Override
        public boolean handleMessage(@NonNull Message msg) {
            if (msg.what == CALLNULL_WHAT_01) {
                String str = (String) msg.obj;
                sSelf.sendCallNumStr(str);
            }
            return false;
        }
    };

    private void sendCallNumStr(String data) {
        ModuleImpl tmpListener = getImpleListener();
        if (tmpListener != null) {
            tmpListener.getNewCallNum(data);
        }
    }

    public void unsetEngineDataListenere() {
        this.moduleImpl = null;
        try {
            service.unsetOnNewCallListener(listener);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        release();
    }


    public void setEngineDataListener(ModuleImpl listener, Looper looper) {
        synchronized (call_lock) {
            this.moduleImpl = listener;
            if (looper != null) {
                mHandler = new Handler(looper, mHandlerCallBack);
            } else {
                mHandler = null;
            }
        }
    }


    @Override
    protected ICallNumAidlInterface onServiceConnectedLocked(IBinder binder) throws RemoteException {
        service = ICallNumAidlInterface.Stub.asInterface(binder);
        service.setOnNewCallListener(listener);
        return service;
    }

    @Override
    protected void onServiceDiedLocked() {
        Log.d(TAG, "[onServiceDiedLocaked()]");
    }

    @Override
    protected void onStateChanged(int state) {
        String str;
        switch (state) {
            case STATE_CONNECTED:
                str = "connected";
                break;
            case STATE_CONNECTING:
                str = "connecting";
                break;
            case STATE_DISCONNECTED:
                str = "disconnected";
                break;
            case STATE_SERVIER_NOT_INSTALL:
                str = "server-not-install";
                break;
            case STATE_SERVIER_DISABLED:
                str = "server-disabled";
                break;
            case STATE_SERVIER_CANT_BIND:
                str = "server-cant-bind";
                break;
            case STATE_SIGNATURE_ERROR:
                str = "signature-error";
                break;
            default:
                str = "unknow-" + state;
        }
        Log.w(TAG, "[onStateChanged]" + str);
    }

    private ICallNumListener listener = new ICallNumListener.Stub() {
        @Override
        public void onNewCallNum(String data) {
            Handler tmpHandler;
            synchronized (call_lock) {
                tmpHandler = mHandler;
            }
            if (tmpHandler != null) {
                tmpHandler.obtainMessage(CALLNULL_WHAT_01, data).sendToTarget();
            } else {
                sendCallNumStr(data);
            }
        }
    };

    public interface ModuleImpl {
        void getNewCallNum(String data);
    }

    private ModuleImpl getImpleListener() {
        synchronized (call_lock) {
            return this.moduleImpl;
        }
    }
}
